//! A lightweight kernel object used to solve the synchronization problem between threads

#![allow(dead_code)]

use crate::base::{CVoid, RTTError};

extern {
    fn rttbase_semaphore_create() -> *const CVoid;
    fn rttbase_semaphore_delete(m: *const CVoid);
    fn rttbase_semaphore_try_take(m: *const CVoid) -> u32;
    fn rttbase_semaphore_take(m: *const CVoid, tick: i32) -> u32;
    fn rttbase_semaphore_release(m: *const CVoid);
}

unsafe impl Send for Semaphore{}
unsafe impl Sync for Semaphore{}

pub struct Semaphore(*const CVoid);

impl Semaphore {

    pub fn new() -> Result<Self, RTTError> {
        let m = unsafe {
            rttbase_semaphore_create()
        };
        if m == 0 as *const _ {
            return Err(RTTError::OutOfMemory);
        }
        Ok(Semaphore(m))
    }

    pub fn try_take(&self) -> Result<(), RTTError> {
        unsafe {
            let m = rttbase_semaphore_try_take(self.0);
            if m != 0 {
                return Err(RTTError::SemaphoreTakeTimeout);
            }
            Ok(())
        }
    }

    pub fn take(&self, max_wait: i32) -> Result<(), RTTError> {
        let ret = unsafe {
            rttbase_semaphore_take(self.0, max_wait)
        };

        if ret != 0 {
            return Err(RTTError::SemaphoreTakeTimeout);
        }

        Ok(())
    }

    pub fn release(&self) {
        unsafe { rttbase_semaphore_release(self.0); }
    }

    fn drop(&mut self) {
        unsafe { rttbase_semaphore_delete(self.0) }
    }
}